{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "from numpy import *"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [],
   "source": [
    "def loadDataSet():\n",
    "    dataMat = []\n",
    "    labelMat = []\n",
    "    fr = open('testSet.txt')\n",
    "    for line in fr.readlines():\n",
    "        lineArr = line.strip().split()\n",
    "        dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])])\n",
    "        labelMat.append(int(lineArr[2]))\n",
    "    return dataMat, labelMat\n",
    "\n",
    "def sigmoid(inX):\n",
    "    # return 1.0 / (1 + exp(-inX))\n",
    "    # 优化方法（RuntimeWarning: overflow encountered in exp）\n",
    "    if inX >= 0:\n",
    "        return 1.0 / (1 + exp(-inX))\n",
    "    else:\n",
    "        return exp(inX) / (1 + exp(inX))\n",
    "\n",
    "# 梯度上升算法\n",
    "def gradAscent(dataMatIn, classLabels):\n",
    "    dataMatrix = mat(dataMatIn)\n",
    "    labelMat = mat(classLabels).transpose()  # 转置为列向量\n",
    "    \n",
    "    m, n = shape(dataMatrix)  # 获取行、列\n",
    "    alpha = 0.001\n",
    "    maxCycles = 500  # 迭代500次\n",
    "    weights = ones((n, 1))\n",
    "    for k in range(maxCycles):\n",
    "        h = sigmoid(dataMatrix * weights)\n",
    "        error = (labelMat - h)  # 误差\n",
    "        weights = weights + alpha * dataMatrix.transpose() * error\n",
    "    return weights"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "matrix([[ 4.12414349],\n",
       "        [ 0.48007329],\n",
       "        [-0.6168482 ]])"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dataArr, labelMat = loadDataSet()\n",
    "weights = gradAscent(dataArr, labelMat)\n",
    "weights"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [],
   "source": [
    "def plotBestFit(wei):\n",
    "    import matplotlib.pyplot as plt\n",
    "    weights = wei.getA()  # 将numpy.mat转换为array类型\n",
    "    \n",
    "    dataMat, labelMat = loadDataSet()\n",
    "    dataArr = array(dataMat)\n",
    "    \n",
    "    n = shape(dataArr)[0]\n",
    "    xcord1 = []\n",
    "    ycord1 = []\n",
    "    xcord2 = []\n",
    "    ycord2 = []\n",
    "    for i in range(n):\n",
    "        if int(labelMat[i]) == 1:\n",
    "            xcord1.append(dataArr[i, 1])\n",
    "            ycord1.append(dataArr[i, 2])\n",
    "        else:\n",
    "            xcord2.append(dataArr[i, 1])\n",
    "            ycord2.append(dataArr[i, 2])\n",
    "            \n",
    "    fig = plt.figure()\n",
    "    ax = fig.add_subplot(111)\n",
    "    ax.scatter(xcord1, ycord1, s=30, c='red', marker='s')\n",
    "    ax.scatter(xcord2, ycord2, s=30, c='green')\n",
    "    \n",
    "    x = arange(-3.0, 3.0, 0.1)  # numpy.arange函数用于创建等差数组\n",
    "    y = (-weights[0] - weights[1] * x) / weights[2]\n",
    "    ax.plot(x, y)\n",
    "    \n",
    "    plt.xlabel('X1')\n",
    "    plt.ylabel('X2')\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plotBestFit(weights)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 训练算法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 随机梯度上升算法\n",
    "def stocGradAscent0(dataMatrix, classLabels):\n",
    "    m, n = shape(dataMatrix)\n",
    "    alpha = 0.01\n",
    "    weights = ones(n)\n",
    "    for i in range(m):\n",
    "        h = sigmoid(sum(dataMatrix[i] * weights))\n",
    "        error = classLabels[i] - h\n",
    "        weights = weights + alpha * error * dataMatrix[i]\n",
    "    return weights"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 1.01702007,  0.85914348, -0.36579921])"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dataArr, labelMat = loadDataSet()\n",
    "weights = stocGradAscent0(array(dataArr), labelMat)\n",
    "weights"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plotBestFit(mat(weights).transpose())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 改进的随机梯度上升算法\n",
    "def stocGradAscent1(dataMatrix, classLabels, numIter=150):\n",
    "    m, n = shape(dataMatrix)\n",
    "    weights = ones(n)\n",
    "    for j in range(numIter):\n",
    "        dataIndex = list(range(m))\n",
    "        for i in range(m):\n",
    "            alpha = 4 / (1.0 + j + i) + 0.01\n",
    "            randIndex = int(random.uniform(0, len(dataIndex)))\n",
    "            h = sigmoid(sum(dataMatrix[randIndex] * weights))\n",
    "            error = classLabels[randIndex] - h\n",
    "            weights = weights + alpha * error * dataMatrix[randIndex]\n",
    "            del dataIndex[randIndex]\n",
    "    return weights"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([14.59078724,  1.01204098, -2.07184784])"
      ]
     },
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dataArr, labelMat = loadDataSet()\n",
    "weights = stocGradAscent1(array(dataArr), labelMat)\n",
    "weights"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plotBestFit(mat(weights).transpose())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 实例 从疝气病预测病马的死亡率"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [],
   "source": [
    "def classifyVector(inX, weights):\n",
    "    prob = sigmoid(sum(inX * weights))\n",
    "    if prob > 0.5:\n",
    "        return 1.0\n",
    "    else:\n",
    "        return 0.0\n",
    "    \n",
    "def colicTest():\n",
    "    frTrain = open('horseColicTraining.txt')\n",
    "    frTest = open('horseColicTest.txt')\n",
    "    trainingSet = []\n",
    "    trainingLabels = []\n",
    "    for line in frTrain.readlines():\n",
    "        currLine = line.strip().split('\\t')\n",
    "        lineArr = []\n",
    "        for i in range(21):\n",
    "            lineArr.append(float(currLine[i]))\n",
    "        trainingSet.append(lineArr)\n",
    "        trainingLabels.append(float(currLine[21]))\n",
    "        \n",
    "    trainWeights = stocGradAscent1(array(trainingSet), trainingLabels, 500)\n",
    "    \n",
    "    errorCount = 0\n",
    "    numTestVec = 0.0\n",
    "    for line in frTest.readlines():\n",
    "        numTestVec += 1.0\n",
    "        currLine = line.strip().split('\\t')\n",
    "        lineArr = []\n",
    "        for i in range(21):\n",
    "            lineArr.append(float(currLine[i]))\n",
    "        if int(classifyVector(array(lineArr), trainWeights)) != int(currLine[21]):\n",
    "            errorCount += 1\n",
    "            \n",
    "    errorRate = float(errorCount) / numTestVec\n",
    "    print('the error rate of this test is: %f' % errorRate)\n",
    "    return errorRate\n",
    "\n",
    "def multiTest():\n",
    "    numTests = 10\n",
    "    errorSum = 0.0\n",
    "    for k in range(numTests):\n",
    "        errorSum += colicTest()\n",
    "    print('after %d iterations the average error rate is: %f' % \n",
    "          (numTests, errorSum / float(numTests)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "the error rate of this test is: 0.388060\n",
      "the error rate of this test is: 0.402985\n",
      "the error rate of this test is: 0.388060\n",
      "the error rate of this test is: 0.358209\n",
      "the error rate of this test is: 0.402985\n",
      "the error rate of this test is: 0.388060\n",
      "the error rate of this test is: 0.388060\n",
      "the error rate of this test is: 0.417910\n",
      "the error rate of this test is: 0.268657\n",
      "the error rate of this test is: 0.343284\n",
      "after 10 iterations the average error rate is: 0.374627\n"
     ]
    }
   ],
   "source": [
    "multiTest()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
